package com.wiz.common.util;

/* 字符串 DESede(3DES) 加密 */
import java.io.UnsupportedEncodingException;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

public class ThreeDes {

    private static final String Algorithm="DESede";

    // 定义

    // 加密算法,可用
    // DES,DESede,Blowfish
    // keybyte为加密密钥，长度为24字节
    // src为被加密的数据缓冲区（源）
    public static String encryptMode(String key, String src) {
        if(src == null){
            return null;
        }
        try {
            // 生成密钥
            SecretKey deskey=new SecretKeySpec(build3DesKey(key), Algorithm);
            // 加密
            Cipher c1=Cipher.getInstance(Algorithm);
            c1.init(Cipher.ENCRYPT_MODE, deskey);
            return byte2hex(c1.doFinal(src.getBytes("utf-8")));
        } catch(java.security.NoSuchAlgorithmException e1) {
            e1.printStackTrace();
        } catch(javax.crypto.NoSuchPaddingException e2) {
            e2.printStackTrace();
        } catch(java.lang.Exception e3) {
            e3.printStackTrace();
        }
        //加密异常返回原数据
        return src;
    }

    // keybyte为加密密钥，长度为24字节
    // src为加密后的缓冲区
    public static String decryptMode(String key, String src) {
        try {
            // 生成密钥
            SecretKey deskey=new SecretKeySpec(build3DesKey(key), Algorithm);
            // 解密
            Cipher c1=Cipher.getInstance(Algorithm);
            c1.init(Cipher.DECRYPT_MODE, deskey);
            return new String(c1.doFinal(hex2byte(src.getBytes("utf-8"))));
        } catch(java.security.NoSuchAlgorithmException e1) {
            e1.printStackTrace();
        } catch(javax.crypto.NoSuchPaddingException e2) {
            e2.printStackTrace();
        } catch(java.lang.Exception e3) {
            e3.printStackTrace();
        }
        return null;
    }

    /*
     * 根据字符串生成密钥字节数组
     * @param keyStr 密钥字符串
     * @return
     * @throws UnsupportedEncodingException
     */
    public static byte[] build3DesKey(String keyStr) throws UnsupportedEncodingException {
        byte[] key=new byte[24]; // 声明一个24位的字节数组，默认里面都是0
        byte[] temp=keyStr.getBytes("UTF-8"); // 将字符串转成字节数组

        /*
         * 执行数组拷贝 System.arraycopy(源数组，从源数组哪里开始拷贝，目标数组，拷贝多少位)
         */
        if(key.length > temp.length) {
            // 如果temp不够24位，则拷贝temp数组整个长度的内容到key数组中
            System.arraycopy(temp, 0, key, 0, temp.length);
        } else {
            // 如果temp大于24位，则拷贝temp数组24个长度的内容到key数组中
            System.arraycopy(temp, 0, key, 0, key.length);
        }
        return key;
    }

    // //转换成十六进制字符串
    // public static String byte2hex(byte[] b) {
    // String hs = "";
    // String stmp = "";
    // for (int n = 0; n < b.length; n++) {
    // stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
    // if (stmp.length() == 1)
    // hs = hs + "0" + stmp;
    // else
    // hs = hs + stmp;
    // if (n < b.length - 1)
    // hs = hs + ":";
    // }
    // return hs.toUpperCase();
    // }

    /**
     * 二行制转字符串
     * @param b
     * @return
     */
    public static String byte2hex(byte[] b) { // 一个字节的数，
        // 转成16进制字符串
        String hs="";
        String stmp="";
        for(int n=0; n < b.length; n++) {
            // 整数转成十六进制表示
            stmp=(java.lang.Integer.toHexString(b[n] & 0XFF));
            if(stmp.length() == 1)
                hs=hs + "0" + stmp;
            else
                hs=hs + stmp;
        }
        return hs.toUpperCase(); // 转成大写
    }

    public static byte[] hex2byte(byte[] b) {
        if((b.length % 2) != 0)
            throw new IllegalArgumentException("长度不是偶数");
        byte[] b2=new byte[b.length / 2];
        for(int n=0; n < b.length; n+=2) {
            String item=new String(b, n, 2);
            // 两位一组，表示一个字节,把这样表示的16进制字符串，还原成一个进制字节
            b2[n / 2]=(byte)Integer.parseInt(item, 16);
        }

        return b2;
    }

    public static void main(String[] args) throws Exception {
//        // 添加新安全算法,如果用JCE就要把它添加进去
//        Security.addProvider(new com.sun.crypto.provider.SunJCE());
        String key="3Fq9d5M2";
//        // 24字节的密钥
//        String szSrc=
//            "<xmlinfo><OrderId>200911111129</OrderId><volume>3</volume><Amount>80</Amount><inceptphone>13316099339</inceptphone><OrderInfo>风声</OrderInfo><OtherInfo>其他信息</OtherInfo><RedirectUri>http://www.baidu.com</RedirectUri></xmlinfo>";
//        System.out.println("加密前的字符串:" + szSrc);
        String encoded=encryptMode(key, "f34fnanas340vcm349AFM9ANAfFU02ao");
        System.out.println("加密后的字符串:" +encoded );
        String srcBytes=decryptMode(key, encoded);
        System.out.println("解密后的字符串:" + (srcBytes));
    }
}
